#include "tcpserver.h"

using namespace VLRTSP;

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 16:16:01
 * 
 * 构造函数
 * @param port 指定监听端口号
 */
TCPServer::TCPServer(uint16_t port) {
	this->serverFd = -1;
	this->port = port;
	this->thread = nullptr;
	this->isRunning = false;
	this->startCallback = nullptr;
	this->doneCallback = nullptr;
	this->recvCallback = nullptr;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 16:16:26
 * 
 * 析构函数
 */
TCPServer::~TCPServer() {
	this->destroy();
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 18:06:41
 * 
 * 设置服务器启动回调函数
 * @param callback 服务器启动回调函数
 */
void TCPServer::setServerStartCallback(ServerStartCallback callback) {
	std::lock_guard<std::mutex> lock(this->mutex);
	this->startCallback = callback;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 18:07:19
 * 
 * 设置服务器结束回调函数
 * @param callback 服务器结束回调函数
 */
void TCPServer::setServerDoneCallback(ServerDoneCallback callback) {
	std::lock_guard<std::mutex> lock(this->mutex);
	this->doneCallback = callback;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 18:08:49
 * 
 * 设置服务器接收 Socket 回调函数
 * @param callback 服务器接收 Socket 回调函数
 */
void TCPServer::setRecvSocketCallback(RecvSocketCallback callback) {
	std::lock_guard<std::mutex> lock(this->mutex);
	this->recvCallback = callback;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 16:17:05
 * 
 * 启动 TCP 服务器
 */
void TCPServer::start() {
	std::lock_guard<std::mutex> lock(this->mutex);
	if(this->isRunning) {
		return;
	}

	this->isRunning = true;
	// 启动线程
	std::thread* thread = new std::thread(&TCPServer::_threadLoop, this);
	thread->detach();
	this->thread = thread;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 16:17:16
 * 
 * 销毁 TCP 服务器
 */
void TCPServer::destroy() {
	this->mutex.lock();
	this->startCallback = nullptr;
	this->doneCallback = nullptr;
	this->recvCallback = nullptr;
	this->isRunning = false;
	if(this->serverFd != -1) {
		this->_destroy();
	}

	std::thread* threadPtr = this->thread;
	this->mutex.unlock();
	if(thread != nullptr) {
		this->thread = nullptr;
		// 等待线程结束
		try {
			if(threadPtr->joinable()) {
				threadPtr->join();
			}
		}
		catch(std::system_error error) {
			// join error, if thread is done, maybe throw this error, ignore
		}
		
		delete threadPtr;
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 17:47:31
 * 
 * 线程循环函数
 */
void TCPServer::_threadLoop() {
	VL_SOCKET fd = this->_listen();
	if(fd == -1) {
		// todo 通知监听端口失败
		this->mutex.lock();
		this->isRunning = false;
		ServerDoneCallback doneCallback = this->doneCallback;
		this->mutex.unlock();
		if(doneCallback) {
			doneCallback();
		}
		return;
	}

	this->serverFd = fd;

	this->mutex.lock();
	ServerStartCallback startCallback = this->startCallback;
	this->mutex.unlock();
	if(startCallback) {
		startCallback();
	}

	while(isRunning) {
		TCPSocket* socket = this->_acceptSocket();
		if(socket != nullptr) {
			this->mutex.lock();
			RecvSocketCallback recvCallback = this->recvCallback;
			this->mutex.unlock();
			std::shared_ptr<TCPSocket> socketPtr(socket);
			if(recvCallback) {
				recvCallback(socketPtr);
			}
			else {
				socket->close();
			}
		}
	}
	this->mutex.lock();
	this->isRunning = false;
	ServerDoneCallback doneCallback = this->doneCallback;
	this->mutex.unlock();
	if(doneCallback) {
		doneCallback();
	}
}